<template>
  <el-row>
    <div
      :class="['search-form', { show: !isShowForm }]"
      :style="{
        flex: 1,
        display: 'flex',
        justifyContent: justify || 'start',
        width: 0,
      }"
    >
      <el-form :model="newSearchForm" v-bind="$attrs" inline>
        <template v-for="item in newFormData">
          <el-form-item
            :label="item.label"
            :prop="item.prop"
            v-if="isTrue(item.display)"
          >
            <!--普通文本框:input-->
            <el-input
              v-if="item.type === 'input'"
              v-model.trim="newSearchForm[item.prop]"
              :minlength="item.min"
              :maxlength="item.max"
              :disabled="item.disabled"
              :readonly="item.readonly"
              :placeholder="item.placeholder || item.message"
              :clearable="isTrue(item.clearable)"
              :style="{ width: (item.width || width || 150) + 'px' }"
            >
            </el-input>

            <!--下拉选择：select-->
            <el-select
              v-if="item.type === 'select'"
              v-model="newSearchForm[item.prop]"
              :multiple="item.multiple"
              :collapse-tags="isTrue(item.collapseTags)"
              collapse-tags-tooltip
              :max-collapse-tags="item.maxCollapseTags || 1"
              :disabled="item.disabled"
              :filterable="item.filterable"
              :clearable="isTrue(item.clearable)"
              :placeholder="item.placeholder || '请选择'"
              :style="{ width: (item.width || width || 150) + 'px' }"
            >
              <template v-if="item.group">
                <el-option-group
                  v-for="group in item.list"
                  :key="group.label"
                  :label="group.label"
                >
                  <el-option
                    v-for="_item in group.options"
                    :key="_item.value"
                    :label="_item.label"
                    :value="_item.value"
                  />
                </el-option-group>
              </template>
              <template v-else>
                <el-option
                  v-for="(_item, _index) in item.list"
                  :key="_index"
                  :label="_item.label"
                  :value="_item.value"
                >
                </el-option>
              </template>
            </el-select>

            <!--日期: date-->
            <el-date-picker
              v-if="item.type === 'date' || item.type === 'daterange'"
              v-model="newSearchForm[item.prop]"
              :type="item.type"
              :placeholder="item.placeholder || '请选择日期'"
              :disabled="item.disabled"
              :startPlaceholder="item.startPlaceholder || '开始日期'"
              :endPlaceholder="item.endPlaceholder || '结束日期'"
              :rangeSeparator="item.rangeSeparator || '至'"
              format="YYYY-MM-DD"
              value-format="YYYY-MM-DD"
              :disabled-date="item.disabledDate"
              :clearable="isTrue(item.clearable)"
              @change="changeVal(newSearchForm, item)"
              :style="{
                width:
                  (item.width || width || (item.type === 'date' ? 150 : 240)) +
                  'px',
              }"
            />

            <!--日期时间: dateTime-->
            <el-date-picker
              v-if="item.type === 'datetime' || item.type === 'datetimerange'"
              v-model="searcnewSearchFormForm[item.prop]"
              :type="item.type"
              :placeholder="item.placeholder || '请选择日期'"
              :disabled="item.disabled"
              :startPlaceholder="item.startPlaceholder || '开始日期'"
              :endPlaceholder="item.endPlaceholder || '结束日期'"
              :rangeSeparator="item.rangeSeparator || '至'"
              format="YYYY-MM-DD HH:mm:ss"
              value-format="YYYY-MM-DD HH:mm:ss"
              :disabled-date="item.disabledDate"
              :clearable="isTrue(item.clearable)"
              @change="changeVal(newSearchForm, item)"
            />
          </el-form-item>
        </template>
      </el-form>
    </div>
    <div>
      <uc-button @click="showForm" v-if="isShowMore" type="text"
        >展开查询<el-icon v-if="isShowForm"><ArrowUp /></el-icon
        ><el-icon v-if="!isShowForm"><ArrowDown /></el-icon
      ></uc-button>
      <uc-button type="primary" @click="search">搜索</uc-button>
      <uc-button @click="resetForm">重置</uc-button>
    </div>
  </el-row>
</template>

<script setup>
import { ref, nextTick, onMounted, toRaw, watch } from "vue";
import { ArrowUp, ArrowDown } from "@element-plus/icons-vue";
import { isTrue, deepClone } from "../../lib";
const emits = defineEmits([
  "update:modelValue",
  "update:searchForm",
  "search",
  "reset",
  "changeVal",
]);
const props = defineProps({
  // 表单配置项
  modelValue: {
    type: Array,
    default: () => {
      return [];
    },
  },
  // 搜索项对象
  searchForm: {
    type: Object,
    default: () => {
      return {};
    },
  },
  // 搜索表单布局
  justify: {
    type: String,
    default: "",
  },
  // 设置表单宽度
  width: {
    type: [Number, String],
    default: "",
  },
  // 是否有清除按钮
  clearable: {
    type: Boolean,
    default: true,
  },
});

/**
 * 计算是否显示展开查询按钮
 */
const isShowMore = ref(false);
const isShowForm = ref(true);
onMounted(() => {
  const searchH = document.querySelector(".search-form").clientHeight;
  if (searchH > 50) {
    isShowMore.value = true;
    isShowForm.value = false;
  }
});
const showForm = () => {
  console.log(2);
  isShowForm.value = !isShowForm.value;
};

/**
 * 同步表单对象到searchForm
 */
let newFormData = ref([]);
let newSearchForm = ref({});

watch(
  () => newSearchForm.value,
  (val) => {
    emits("update:searchForm", val);
  }
);

/**
 * 初始化或重置表单对象，通过表单配置项生成表单对象,使用默认的searchForm进行覆盖
 * 表单对象为：display显示并且有prop属性
 */
const initForm = (searchForm = {}) => {
  newFormData.value = deepClone(props.modelValue);
  const keys = {};
  props.modelValue
    .filter((item) => isTrue(item.display) && item.prop)
    .forEach((item) => {
      keys[item.prop] = item.value;
    });
  nextTick(() => {
    newSearchForm.value = { ...keys, ...searchForm };
  });
};

/**
 * 监听表单配置项, 渲染表单并生成表单对象
 */
watch(
  () => props.modelValue,
  (val) => {
    if (val.length > 0) {
      initForm(props.searchFormForm);
    }
  },
  {
    immediate: true,
  }
);

/**
 * 修改表单对象属性值
 * @param { string } obj 属性对象
 */
const modifyFormValue = (obj) => {
  newSearchForm.value = {
    ...newSearchForm.value,
    ...obj,
  };
};

/**
 * 修改表单配置项，如果修改display属性则显示或隐藏对应的属性
 * 显示表单项时，是否需要保持为上一次的值
 * @param { string } obj 属性对象
 */
const modifyFormConfig = (obj) => {
  for (let key in obj) {
    const index = newFormData.value.findIndex((item) => item.prop === key);
    if (index > -1) {
      for (let prop in obj[key]) {
        newFormData.value[index][prop] = obj[key][prop];
        if (prop === "value") newSearchForm.value[key] = obj[key][prop];
        if (prop === "display" && obj[key][prop])
          newSearchForm.value[key] = newFormData.value[index].value;
        if (prop === "display" && !obj[key][prop])
          delete newSearchForm.value[key];
      }
    }
  }
};

/**
 * 处理表单数据
 * 当有日期区间时，对数据进行处理，绑到到真实的属性上
 */
const getSearchForm = (keys) => {
  const newSearchForm = structuredClone(toRaw(keys));
  props.modelValue
    .filter(
      (item) =>
        (item.type == "daterange" || item.type == "datetimerange") && item.props
    )
    .forEach((item) => {
      if (newSearchForm[item.prop] && newSearchForm[item.prop].length > 0) {
        newSearchForm[item.props[0]] = newSearchForm[item.prop][0];
        newSearchForm[item.props[1]] = newSearchForm[item.prop][1];
      }
      delete newSearchForm[item.prop];
    });
  return newSearchForm;
};

/**
 * 监听表单项处理数据变化
 * 处理日期区间数据
 */
const changeVal = (searchForm, item) => {
  emits("changeVal", searchForm, item);
};

/**
 * 点击搜索
 * 当前搜索表单对象作为参数传递
 */
const search = () => {
  emits("search", toRaw(newSearchForm.value));
};

/**
 * 重置搜索
 * @param { boolean } tag 点击重置是否触发搜索事件 true触发 false不触发
 */
const resetForm = (tag = true) => {
  initForm();
  setTimeout(() => {
    if (tag) search();
    emits("reset");
  });
};

defineExpose({
  resetForm,
  modifyFormValue,
  modifyFormConfig,
});
</script>

<style scoped lang="scss">
.search-form {
  &.show {
    height: 50px;
    overflow: hidden;
  }
}
</style>
